package room

import (
	"context"
	"encoding/json"
	"game_server/dao/room"
	"game_server/framework/connection"
	"game_server/framework/global"
	"game_server/framework/message"
	"game_server/framework/task"
	"game_server/game"
	"game_server/game/model"
	"game_server/proto"
	"game_server/tool"
	"log"
	"strings"
	"time"

	"github.com/duke-git/lancet/v2/convertor"
	"github.com/spf13/viper"
)

type RoomJoinReq struct {
	RoomLevel int `json:"roomLevel"`
}

func RoomConfigHandler(taskWrapper *task.TaskWrapper) *task.TaskWrapper {
	defer func() {
		err := recover()
		if err != nil {
			global.Logger.Errorf("err:%v", err)
		}
	}()
	defer global.Logger.Info("package:[room]:::function:[RoomConfigHandler]<======")
	global.Logger.Infof("======>package:[room]:::function:[RoomConfigHandler]:::id:%v", taskWrapper.ReceiverId)
	roomInfoRes := make([]proto.RoomConfigInfoRes, 0)
	roomsdb := room.QueryAll()
	for _, v := range roomsdb {
		roomConfigInfo := proto.RoomConfigInfoRes{}
		convertor.CopyProperties(&roomConfigInfo, v)
		roomInfoRes = append(roomInfoRes, roomConfigInfo)
	}
	messageWrapper := &message.MessageWrapper{Code: proto.ROOMCONFIG, Data: roomInfoRes}
	task := &task.TaskWrapper{
		ReceiverId:     taskWrapper.ReceiverId,
		MessageWrapper: messageWrapper,
		SenderIds:      []int64{taskWrapper.ReceiverId},
	}
	return task
}

func RoomJoinHandler(taskWrapper *task.TaskWrapper) *task.TaskWrapper {
	defer func() {
		err := recover()
		if err != nil {
			global.Logger.Errorf("err:%v", err)
		}
	}()
	defer global.Logger.Info("package:[room]:::function:[RoomJoinHandler]<======")
	global.Logger.Infof("======>package:[room]:::function:[RoomJoinHandler]:::id:%v", taskWrapper.ReceiverId)
	playerId := taskWrapper.ReceiverId
	roomJoinReq := &RoomJoinReq{}
	json.Unmarshal([]byte(convertor.ToString(taskWrapper.MessageWrapper.Data)), roomJoinReq)
	result, err := global.RedisClient.Get(context.Background(), viper.GetString("redis.player-key")+convertor.ToString(playerId)).Result()
	global.Logger.Infof("======>package:[room]:::function:[RoomJoinHandler]:::roomJoinReq:%v", roomJoinReq)
	if err != nil {
		log.Fatal("roomInfo is nil")
		game.GameManagerInstance().LevelRoom(playerId)
		connection.InitConnectionManager().RemoveConn(playerId)
		return nil
	}
	//global.Logger.Infof("======>package:[room]:::function:[RoomJoinHandler]:::111111")
	roomInfo := game.GameManagerInstance().RoomInfos[roomJoinReq.RoomLevel]
	if roomInfo == nil {
		log.Fatal("roomInfo is nil")
		return nil
	}
	log.Println("levelConfig:", roomInfo.RoomConfig.LevelConfig)
	//global.Logger.Infof("======>package:[room]:::function:[RoomJoinHandler]:::222222")
	playerInfo := model.PlayerInfo{}
	json.Unmarshal([]byte(result), &playerInfo)
	levelResult := false
	levelConfigs := strings.Split(roomInfo.RoomConfig.LevelConfig, ",")
	for _, v := range levelConfigs {
		levelInt, _ := convertor.ToInt(v)
		if levelInt == playerInfo.Level {
			levelResult = true
		}
	}
	//global.Logger.Infof("======>package:[room]:::function:[RoomJoinHandler]:::333333")
	if !levelResult {
		log.Fatal("levelResult is false")
		return nil
	}
	//global.Logger.Infof("======>package:[room]:::function:[RoomJoinHandler]:::444444")
	if playerInfo.Coins < roomInfo.RoomConfig.EnterCoin {
		log.Fatal("playerInfo.Coins < roomInfo.RoomConfig.EnterCoin")
		return nil
	}
	//global.Logger.Infof("======>package:[room]:::function:[RoomJoinHandler]:::555555")
	roomLevel := 0
	for _, v := range game.GameManagerInstance().RoomInfos {
		_, ok := v.PlayerInfos.Get(playerInfo.Id)
		if ok {
			roomLevel = v.RoomConfig.RoomLevel
		}
	}
	if roomLevel != roomJoinReq.RoomLevel {
		game.GameManagerInstance().LevelRoom(playerInfo.Id)
	}
	playerInfo.LastBetTimeStamp = tool.CurrentTimestamp()
	jsonStr, _ := convertor.ToJson(playerInfo)
	tokenTime := viper.GetInt("redis.token-time")
	global.RedisClient.Set(context.Background(), viper.GetString("redis.player-key")+convertor.ToString(playerInfo.Id), jsonStr, time.Duration(tokenTime)*time.Minute)
	game.GameManagerInstance().JoinRoom(&playerInfo, roomJoinReq.RoomLevel)
	//global.Logger.Infof("======>package:[room]:::function:[RoomJoinHandler]:::开始同步消息")
	roomInfo.SynRoomInfo()
	roomInfo.SynPlayerInfo()
	roomInfo.SynBetInfo()
	roomInfo.SynPrizeInfo()
	//global.Logger.Infof("======>package:[room]:::function:[RoomJoinHandler]:::结束同步消息")
	messageWrapper := &message.MessageWrapper{Code: proto.ROOMJOIN, Data: "OK"}
	task := &task.TaskWrapper{
		ReceiverId:     taskWrapper.ReceiverId,
		MessageWrapper: messageWrapper,
		SenderIds:      []int64{taskWrapper.ReceiverId},
	}
	//global.Logger.Infof("======>package:[room]:::function:[RoomJoinHandler]:::完成handler")
	return task
}

func RoomExitHandler(taskWrapper *task.TaskWrapper) *task.TaskWrapper {
	defer func() {
		err := recover()
		if err != nil {
			global.Logger.Errorf("err:%v", err)
		}
	}()
	defer global.Logger.Info("package:[room]:::function:[RoomExitHandler]<======")
	global.Logger.Infof("======>package:[room]:::function:[RoomExitHandler]:::id:%v", taskWrapper.ReceiverId)
	playerId := taskWrapper.ReceiverId
	exists := global.RedisClient.Exists(context.Background(), viper.GetString("redis.player-key")+convertor.ToString(playerId)).Val()
	if exists != 1 {
		game.GameManagerInstance().LevelRoom(playerId)
		connection.ConnectionManagerInstance().RemoveConn(playerId)
		return nil
	}
	result := global.RedisClient.Get(context.Background(), viper.GetString("redis.player-key")+convertor.ToString(playerId)).Val()
	playerInfo := model.PlayerInfo{}
	json.Unmarshal([]byte(result), &playerInfo)
	roomInfo := game.GameManagerInstance().QueryRoomInfo(playerId)
	if roomInfo == nil {
		return nil
	}
	p, ok := roomInfo.PlayerInfos.Get(playerId)
	if !ok {
		return nil
	}
	if p.IsGaming {
		return nil
	}
	game.GameManagerInstance().LevelRoom(playerId)
	playerInfo.LastBetTimeStamp = tool.CurrentTimestamp()
	jsonStr, _ := convertor.ToJson(playerInfo)
	tokenTime := viper.GetInt("redis.token-time")
	global.RedisClient.Set(context.Background(), viper.GetString("redis.player-key")+convertor.ToString(playerInfo.Id), jsonStr, time.Duration(tokenTime)*time.Minute)
	messageWrapper := &message.MessageWrapper{Code: proto.ROOMEXIT, Data: playerInfo.Id}
	task := &task.TaskWrapper{
		ReceiverId:     taskWrapper.ReceiverId,
		MessageWrapper: messageWrapper,
		SenderIds:      []int64{taskWrapper.ReceiverId},
	}
	return task
}
